﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace TextDataExtractor.DEML {
	public abstract class DemlElement : IDemlElement {
		
		private IDictionary<string, string> arguments;
		private string name, tagName;
		private IList<IDemlElement> subElements = new List<IDemlElement>();
				
		public IDictionary<string, string> Arguments {
			get {
				return this.arguments != null ? arguments : arguments = new Dictionary<string, string>();
			}
		}

		public DemlRegistry Registry { get; protected set; }

		public IList<IDemlElement> Children { get { return subElements; } }

		public IEnumerable<T> getChildren<T>() where T: IDemlElement {
			foreach (var t in subElements)
				if (t is T)
					yield return (T)t;
		}

		public string Name {
			get {
				return this.name;
			}
			set {
				this.name = value;
			}
		}

		public string Operation {
			get;
			private set;
		}

		public virtual string FullName { get { return name; } }

		public virtual void loadFromXml(XmlNode node, DemlRegistry registry) {
			Operation = node.Name;
			this.Registry = registry;
			foreach (XmlAttribute a in node.Attributes)
				Arguments[a.Name] = a.Value;

			Name = getArgument("name");

			if (node.HasChildNodes)
				foreach (XmlNode child in node.ChildNodes)
					processChildNode(child, registry);
		}

		protected virtual void processChildNode(XmlNode child, DemlRegistry registry) {
		}

		public string getArgument(string name) {
			return Arguments.ContainsKey(name) ? Arguments[name] : string.Empty;
		}

		public override string ToString() {
			return string.Format("{0} {1} [{2}]", Operation, FullName, this.GetType().Name);
		}

		public virtual DemlElement Clone() {
			DemlElement target = (DemlElement)Activator.CreateInstance(this.GetType());
			CopyTo(target);
			return target;
		}

		public virtual void CopyTo(DemlElement target) {
			foreach (KeyValuePair<string, string> p in Arguments)
				target.Arguments[p.Key] = p.Value;
			foreach (IDemlElement sub in subElements)
				target.subElements.Add((IDemlElement)sub.Clone());
			target.Name = name;
		}

		object ICloneable.Clone() {
			return Clone();
		}
	}
}
